package com.dragon.modules.yuegou.service.impl.act;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.exception.DragonException;
import com.dragon.modules.yuegou.entity.act.GiftBagEntity;
import com.dragon.modules.yuegou.entity.act.GiftBagMemberProRefEntity;
import com.dragon.modules.yuegou.entity.act.GiftBagMemberRefEntity;
import com.dragon.modules.yuegou.entity.act.GiftBagProRefEntity;
import com.dragon.modules.yuegou.entity.coupon.CouponEntity;
import com.dragon.modules.yuegou.entity.product.SkuEntity;
import com.dragon.modules.yuegou.enums.YsqAppType;
import com.dragon.modules.yuegou.enums.act.GiftBagMemberProRefSkuType;
import com.dragon.modules.yuegou.enums.act.GiftBagProRefSkuType;
import com.dragon.modules.yuegou.enums.code.ActivityCode;
import com.dragon.modules.yuegou.enums.order.OrderBuyerType;
import com.dragon.modules.yuegou.enums.order.OrderStatus;
import com.dragon.modules.yuegou.enums.order.OrderType;
import com.dragon.modules.yuegou.enums.product.StockChangeType;
import com.dragon.modules.yuegou.excel.act.IssueDetailWorkbook;
import com.dragon.modules.yuegou.mapper.act.GiftBagMemberRefMapper;
import com.dragon.modules.yuegou.model.act.GiftBagMemberProRef;
import com.dragon.modules.yuegou.model.act.GiftBagMemberRef;
import com.dragon.modules.yuegou.model.coupon.Coupon;
import com.dragon.modules.yuegou.model.order.Goods;
import com.dragon.modules.yuegou.model.order.Order;
import com.dragon.modules.yuegou.model.order.OrderPay;
import com.dragon.modules.yuegou.model.system.Document;
import com.dragon.modules.yuegou.query.act.GiftBagMemberProRefQuery;
import com.dragon.modules.yuegou.query.act.GiftBagMemberRefQuery;
import com.dragon.modules.yuegou.query.act.GiftBagProRefQuery;
import com.dragon.modules.yuegou.service.act.GiftBagMemberProRefService;
import com.dragon.modules.yuegou.service.act.GiftBagMemberRefService;
import com.dragon.modules.yuegou.service.act.GiftBagProRefService;
import com.dragon.modules.yuegou.service.act.GiftBagService;
import com.dragon.modules.yuegou.service.coupon.CouponService;
import com.dragon.modules.yuegou.service.coupon.CouponTemplateService;
import com.dragon.modules.yuegou.service.member.MemberService;
import com.dragon.modules.yuegou.service.order.GoodsService;
import com.dragon.modules.yuegou.service.order.OrderService;
import com.dragon.modules.yuegou.service.product.SkuService;
import com.dragon.modules.yuegou.service.product.StockService;
import com.dragon.modules.yuegou.service.system.DocumentService;
import com.dragon.modules.yuegou.utils.PrivateStringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 礼包发放记录表 服务实现
 *
 * @author pbuilder generated
 * @date 2020-08-05 18:40:34
 * @version 2.0
 */
@Service("actGiftBagMemberRefService")
public class GiftBagMemberRefServiceImpl
		extends ServiceImpl<GiftBagMemberRefMapper, GiftBagMemberRefEntity>
		implements GiftBagMemberRefService {

	@Autowired
	private GiftBagService giftBagService;

	@Autowired
	private MemberService memberService;

	@Autowired
	private CouponService couponService;

	@Autowired
	private CouponTemplateService couponTemplateService;

	@Autowired
	private GiftBagProRefService giftBagProRefService;

	@Autowired
	private OrderService orderService;

	@Autowired
	private GoodsService goodsService;

	@Autowired
	private SkuService skuService;

	@Autowired
	private StockService stockService;

	@Autowired
	private DocumentService documentService;

	@Autowired
	private GiftBagMemberProRefService giftBagMemberProRefService;

	@Override
	@Transactional
	public List<GiftBagMemberRef> issueGiftBag(String giftBagId, String createdBy, List<String> mobileList) {
		GiftBagEntity giftBag = giftBagService.getById(giftBagId);
		LocalDateTime createdTime = LocalDateTime.now();
		GiftBagProRefQuery query = new GiftBagProRefQuery();
		query.setGiftBagId(giftBag.getId());
		List<GiftBagProRefEntity> proRefList = giftBagProRefService.list(query.toQueryWrapper());

		List<GiftBagMemberRef> giftBagMemberRefList = mobileList.stream().map(mobile ->{
			if (PrivateStringUtils.isNotMobileNO(mobile)){
				throw new DragonException(ActivityCode.PHONE_WRONG_FORMAT.getCode(),String.format(ActivityCode.PHONE_WRONG_FORMAT.getMessage(),mobile));
			}
			String memberId = memberService.createMember(giftBag.getBusdId(),mobile, YsqAppType.YSQ_GROUP);
			GiftBagMemberRef giftBagMemberRef = new GiftBagMemberRef();
			giftBagMemberRef.setBusdId(giftBag.getBusdId());
			giftBagMemberRef.setGiftBagId(giftBag.getId());
			giftBagMemberRef.setMemberId(memberId);
			giftBagMemberRef.setGiftBagName(giftBag.getBagName());
			giftBagMemberRef.setMobile(mobile);
			giftBagMemberRef.setNum(1);
			giftBagMemberRef.setCreatedTime(createdTime);
			giftBagMemberRef.setCreatedBy(createdBy);
			giftBagMemberRef.setWithdraw(false);
			baseMapper.insert(giftBagMemberRef);

			return giftBagMemberRef;
		}).collect(Collectors.toList());

		Map<String,List<GiftBagMemberRef>> map = giftBagMemberRefList.stream().collect(Collectors.groupingBy(GiftBagMemberRef::getMemberId));

		List<String> memberIdList = giftBagMemberRefList.stream().map(GiftBagMemberRef::getMemberId).collect(Collectors.toList());
		List<GiftBagMemberProRefEntity> memberProRefList = new ArrayList<>();
		proRefList.stream().forEach(giftBagProRef -> {
			if (giftBagProRef.getSkuType().equals(GiftBagProRefSkuType.SKU)){
				List<Order>  orderList = batchPreOrder(memberIdList,giftBagProRef.getSkuId(),giftBag.getBusdId(),giftBagProRef.getNum());
				List<GiftBagMemberProRef> skuGiftBagMemberProRef = addGiftBagMemberProRef(map,GiftBagMemberProRefSkuType.SKU,orderList,null);
				memberProRefList.addAll(skuGiftBagMemberProRef);

			}else if (giftBagProRef.getSkuType().equals(GiftBagProRefSkuType.PARKCOUPON)){
				Set<String> memberSet = new HashSet<>(memberIdList);
				List<Coupon> couponList = couponService.issueCoupon(memberSet,giftBagProRef.getTemplateId(),"后台发放礼包",giftBagProRef.getNum());
				List<GiftBagMemberProRef> parkGiftBagMemberProRef = addGiftBagMemberProRef(map,GiftBagMemberProRefSkuType.PARKCOUPON,null,couponList);
				memberProRefList.addAll(parkGiftBagMemberProRef);

			}else if (giftBagProRef.getSkuType().equals(GiftBagProRefSkuType.CASHCOUPON)){
				List<Coupon> couponList = couponTemplateService.issueCoupon(memberIdList,giftBagProRef.getTemplateId(),giftBagProRef.getNum());
				List<GiftBagMemberProRef> cashGiftBagMemberProRef = addGiftBagMemberProRef(map, GiftBagMemberProRefSkuType.CASHCOUPON,null,couponList);
				memberProRefList.addAll(cashGiftBagMemberProRef);
			}
		});
		giftBagMemberProRefService.saveBatch(memberProRefList);

		//扣库存
		stockService.changeStock(giftBag.getSkuId(),0-giftBagMemberRefList.size(), StockChangeType.ORDER);
		return giftBagMemberRefList;
	}

	private List<Order> batchPreOrder(List<String> memberIdList,String skuId,String busdId,Integer num){
		SkuEntity sku = skuService.getById(skuId);
		return memberIdList.stream().map(memberId ->{
			// 创建订单
			Order orderRequest = new Order();// 准备OrderRequest
			orderRequest.setType(OrderType.BUY);
			orderRequest.setBusdId(busdId);
			orderRequest.setBuyerId(memberId);
			orderRequest.setBuyerType(OrderBuyerType.MEMBER);
			orderRequest.addItem(sku.getId(), num);
			orderRequest.setCouponAmount(sku.getDiscountPrice().multiply(new BigDecimal(num)));// 优惠金额
			Order order = orderService.issueOrder(orderRequest);

			OrderPay orderPay = new OrderPay();
			orderPay.setOrderNo(order.getId());
			orderPay.setPayTime(LocalDateTime.now());
			orderPay.setPayCash(order.getPayableAmount());
			orderService.payZeroOrder(orderPay);

			return order;
		}).collect(Collectors.toList());
	}

	private  List<GiftBagMemberProRef> addGiftBagMemberProRef(Map<String,List<GiftBagMemberRef>> map, GiftBagMemberProRefSkuType skuType, List<Order>orderList, List<Coupon> couponList){
		List<GiftBagMemberProRef> memberProRefList = new ArrayList<>();

		if(CollectionUtils.isNotEmpty(orderList)){
			for(Order order :orderList){
				List<GiftBagMemberRef> giftBagMemberRefList = map.get(order.getBuyerId());
				memberProRefList.addAll(conversionGiftBagMemberProRef(giftBagMemberRefList,order.getId(),null,skuType));
			}
		}
		if(CollectionUtils.isNotEmpty(couponList)){
			for(Coupon coupon :couponList){
				List<GiftBagMemberRef> giftBagMemberRefList = map.get(coupon.getMemberId());
				memberProRefList.addAll(conversionGiftBagMemberProRef(giftBagMemberRefList,null,coupon.getId(),skuType));
			}
		}

		return memberProRefList;
	}
	private List<GiftBagMemberProRef> conversionGiftBagMemberProRef(List<GiftBagMemberRef> giftBagMemberRefList,String orderNo,String couponId,GiftBagMemberProRefSkuType skuType){

		return giftBagMemberRefList.stream().map(giftBagMemberRef -> {
			GiftBagMemberProRef memberProRef = new GiftBagMemberProRef();
			memberProRef.setGiftBagId(giftBagMemberRef.getGiftBagId());
			memberProRef.setGiftMemberId(giftBagMemberRef.getId());
			memberProRef.setCouponId(couponId);
			memberProRef.setOrderNo(orderNo);
			memberProRef.skuType(skuType);
			return memberProRef;
		}).collect(Collectors.toList());
	}

	@Override
	@Transactional
	public GiftBagMemberRef withdrawGiftBag(String issueDetailId) {
		GiftBagMemberRefEntity memberRef = this.getById(issueDetailId);
		if (memberRef==null || StringUtils.isEmpty(memberRef.getId())){
			throw new DragonException(ActivityCode.ISSUEDETAIL_NOT_FIND);
		}
		GiftBagMemberProRefQuery query = new GiftBagMemberProRefQuery();
		query.setGiftMemberId(memberRef.getId());
		List<GiftBagMemberProRefEntity> memberProRefList = giftBagMemberProRefService.list(query.toQueryWrapper());
		if (CollectionUtils.isNotEmpty(memberProRefList)){
			memberProRefList.stream().forEach(this::updateStatus);
		}

		memberRef.setWithdraw(true);
		baseMapper.updateById(memberRef);

		return new GiftBagMemberRef(memberRef);
	}

	private void updateStatus(GiftBagMemberProRefEntity giftBagMemberProRef){
		switch (giftBagMemberProRef.getSkuType()){
			case SKU :
				Order order = orderService.getOrder(giftBagMemberProRef.getOrderNo());

				List<Goods> goodsList = goodsService.listByOrder(order.getId());

				List<Goods> pickupList =  goodsList.stream().filter(Goods::getPickup).collect(Collectors.toList());
				if (CollectionUtils.isNotEmpty(pickupList)){
					throw new DragonException(ActivityCode.GOODS_PICKUP);
				}
				order.setStatus(OrderStatus.CLOSED);

				orderService.updateStatus(order);
				break;
			case PARKCOUPON:
				CouponEntity parkcoupon = couponService.getById(giftBagMemberProRef.getCouponId());
				if (parkcoupon.getUsed()){
					throw new DragonException(ActivityCode.GOODS_PICKUP);
				}
				parkcoupon.setExpired(true);
				couponService.updateById(parkcoupon);
				break;
			case CASHCOUPON:
				CouponEntity coupon = couponService.getById(giftBagMemberProRef.getCouponId());
				if (coupon.getUsed()){
					throw new DragonException(ActivityCode.GOODS_PICKUP);
				}
				coupon.setExpired(true);
				couponService.updateById(coupon);
				break;
			default:
				break;
		}
	}

	@Override
	public Document exportIssueDetail(GiftBagMemberRefQuery query) {
		List<GiftBagMemberRefEntity> list = list(query.toQueryWrapper());

		IssueDetailWorkbook issueDetailWorkbook = new IssueDetailWorkbook();
		List<IssueDetailWorkbook.IssueDetailRow> issueDetailRowList = new ArrayList<>();
		if(list != null && list.size() > 0) {
			for (GiftBagMemberRefEntity giftBagMemberRef : list){
				IssueDetailWorkbook.IssueDetailRow issueDetailRow = new IssueDetailWorkbook.IssueDetailRow();
				issueDetailRow.setMobile(giftBagMemberRef.getMobile());
				issueDetailRow.setGiftBagName(giftBagMemberRef.getGiftBagName());
				if (giftBagMemberRef.getWithdraw()) {
					issueDetailRow.setWithdraw("撤回");
				} else {
					issueDetailRow.setWithdraw("未撤回");
				}
				issueDetailRow.setIssueTime(giftBagMemberRef.getCreatedTime());
				issueDetailRowList.add(issueDetailRow);
			}
		}
		issueDetailWorkbook.setIssueDetail(issueDetailRowList);
		return documentService.generateExcel("礼包发放记录表", issueDetailWorkbook);
	}
}